import tkinter as tk
from tkinter import ttk
from tkinter import *
import abc

# 主页面
import consul_register


class MainApp(object):
    tab_map = {}

    def __init__(self, title=None, geometry='500x300'):
        win = tk.Tk()
        win.geometry(geometry)
        win.resizable(0, 0)
        if title is not None:
            win.title(title)
        self.tabControl = ttk.Notebook(win, style="")
        self.win = win

    def create_tab(self, tab_name, tab_factory):
        self.tab_map.__setitem__(tab_name, tab_factory(self.tabControl))
        return self

    def exec_fun(self, fun):
        fun(self)
        return self

    def tab(self, tab_name):
        return self.tab_map.get(tab_name)

    def refresh(self, tab_name):
        self.tab(tab_name).refresh(self.win)
        return self

    def run(self):
        self.win.mainloop()
        return self


# tab 抽象类
class BasicTab(metaclass=abc.ABCMeta):
    current_row = 0
    label = {}
    input = {}
    check_button = {}
    button = {}

    class Elem(object):
        def __init__(self, source, name, var, event=None):
            self.source = source
            self.name = name
            self.var = var
            self.event = event

    def __init__(self, tab_name, tab_control):
        self.tab_name = tab_name
        self.table_frame = ttk.Frame(tab_control)

        tab_control.add(self.table_frame, text=self.tab_name)
        tab_control.grid(column=1, row=self.current_row)

    def handle(self):
        pass

    def next_row(self):
        self.current_row = self.current_row + 1
        return self

    def lab(self, name, text=None, height=2, width=20, column=0, columnspan=1, event=None):
        source = Label(self.table_frame, text=text, height=height, width=width)
        source.grid(column=column, columnspan=columnspan, row=self.current_row)
        self.label.__setitem__("lab_" + name,
                               BasicTab.Elem(source, name, text, event))
        return self

    def inp(self, name, text, width=20, column=0, columnspan=1):
        var = StringVar()
        var.set(text)
        source = Entry(self.table_frame, textvariable=var, width=width)
        source.grid(column=column, columnspan=columnspan, row=self.current_row)
        self.input.__setitem__("inp_" + name, BasicTab.Elem(source, name, var))
        return self

    def get_inp(self, name):
        return self.input.get("inp_" + name)

    def check_btn(self, name, text, checked=0, width=20, column=0, event=None):
        var = IntVar(value=checked)
        c_btn = Checkbutton(self.table_frame, text=text, variable=var, onvalue=1, offvalue=0,
                            height=1, width=width)
        c_btn.select() if checked == 1 else c_btn.deselect()
        c_btn.grid(column=column, row=self.current_row)
        self.check_button.__setitem__("c_btn_" + name, BasicTab.Elem(c_btn, name, var, event))
        return self

    def get_check_btn(self, name):
        return self.check_button.get("c_btn_" + name)

    def btn(self, name, text, command, height=1, width=20, column=0):
        self.button.__setitem__(name, Button(self.table_frame, text=text, height=height, width=width,
                                             command=command)
                                .grid(column=column, row=self.current_row))
        return self

    def refresh(self, win):
        pass

    def to_string(self):
        return "tabName:" + self.tab_name


# consul服务管理
class ConsulTab(BasicTab):
    def __init__(self, tab_name, tab_control, tab_input):
        super().__init__(tab_name, tab_control)
        self.tab_input = tab_input

    def handle(self):
        print(self.to_string())

    def refresh(self, win):
        win.after(1000, self.ref())

    def ref(self):
        for server in self.check_button.items():
            el = server[1]
            if el.event is not None:
                el.var.setel.event(el.name)
                el.source.update()
        for server in self.label.items():
            el = server[1]
            if el.event is not None:
                status = el.event(el.name)
                ch_btn = self.get_check_btn(el.name)
                ch_btn.var.set(1 if status.startswith("passing") else 0)
                el.source["text"] = status
                ch_btn.source.update()
                el.source.update()


# 其他服务管理
class ServiceTab(BasicTab):
    def __init__(self, tab_name, tab_control, tab_input):
        super().__init__(tab_name, tab_control)
        self.tab_input = tab_input

    def handle(self):
        print(self.to_string())

    def to_string(self):
        return "tabName:" + self.tab_name + "\n" + "input:" + self.tab_input.get()


# 配置consul_tab
def config_consul_tab(consul_lab, win, register_host="127.0.0.1"):
    # 获取输入框host

    consul_lab = consul_lab \
        .next_row() \
        .lab(name="env", text="请选择服务所在环境:", column=1) \
        .inp(name="env", text="192.168.4.31", column=2, columnspan=2) \
        .next_row() \
        .lab(name="server_name", text="服务名称:", column=1) \
        .lab(name="state", text="注册状态：健康状态", column=2, columnspan=2) \
        .next_row()

    host = consul_lab.get_inp("env").var

    # 获取所有consul服务
    all_services = consul_register.all_service(apollo_url="http://" + host.get() + ":8083/",
                                               register_host=register_host)

    # 设置服务信息
    for service in all_services.items():
        status = service[1].status
        consul_lab \
            .check_btn(name=service[0], text=service[0],
                       checked=1 if status.startswith("passing") else 0, column=1) \
            .lab(name=service[0], text=status, width=26, column=2, columnspan=2,
                 event=lambda ser: consul_register.health_check(register_host, ser)) \
            .next_row()

    checked_map = {}
    for service in consul_lab.check_button.items():
        checked_map.__setitem__(service[1].name, service[1].var)

    # 底部按钮
    consul_lab \
        .btn(name="btn_consul_res", text="注册",
             command=
             lambda: consul_register.res(services_map=checked_map, service_port_map=all_services, host_addr=host),
             width=13, column=1) \
        .btn(name="btn_consul_deres", text="注销",
             command=
             lambda: consul_register.deres(services_map=checked_map, service_port_map=all_services, host_addr=host),
             width=13, column=2) \
        .btn(name="btn_consul_ref", text="刷新",
             command=
             lambda: consul_lab.refresh(win),
             width=13, column=3)


if __name__ == '__main__':
    MainApp(title="自选小工具", geometry='430x500') \
        .create_tab("consul", lambda a: ConsulTab("consul", a, "consul输入")) \
        .create_tab("service", lambda a: ServiceTab("service", a, "service输入")) \
        .exec_fun(lambda a: config_consul_tab(a.tab("consul"), a.win, "127.0.0.1")) \
        .run()
